/**
* Основное состояние интерфейса, с него возможен переход на два других состояния.
* Выход и вход (всмысле интерфейса пользователя) в это приложение осуществляется через это состояние.
*
* Другие состояния: создание раздела (класс SectionCreate) и редактирование раздела (SectionSettings)
* Эти два состояния используют SectionForm для работы с формой.
*
* Для создания экземпляра этого класса используется элемент содержащий фон.
* Подразумевается, что после него этот класс будет создавать свои элементы. По прекращении работы удалит.
*
* @author Alexander Sibiryakov
*/
function SectionsManager(bg_elt) {
	this._bg_elt = bg_elt; // элемент фона, или любой другой элемент после которого делать вставки содержащие гуй
	this._de = null;
	this.sections = new Array(); // список разделов
	this.template = null;
	this._tpl_url = jQuery("a.js_tpl_url").attr("href");
	this._ajax_url = jQuery("a.js_sect_settings_url").attr("href");
	this.selected_oid = null;

	/*
	* рендерит список разделов и вставляет в дом
	* назначит this._de элемент дома
	*/
	this.initDom = function() {

		this.template = jQuery.createTemplateURL(this._tpl_url +"/WG_SectionsManage:init");

		cp.set_env_object(this);
		cp.call(this._ajax_url, 'ajax_getSections', function(result) {
			var items = new Array();
			if (result.ajaxResponse[0].section) {
				jQuery(result.ajaxResponse[0].section).each(
				function() {
					var item = {};
					item['oid'] = this.oid[0].data;
					item['num'] = this.num[0].data;
					item['title'] = this.title[0].data;
					item['items_count'] = this.items_cnt[0].data;
					if (items.length == 0) {
						item['active'] = 1;
						items[0] = item;
					} else {
						items[items.length] = item;
					}
				}
				);
				this.selected_oid = items[0].oid; // выбран по умолчанию первый раздел
			}

			jQuery(this._bg_elt).after('<div id="section-manager"></div>');
			jQuery("#section-manager").setTemplate(this.template);
			jQuery("#section-manager").setParam("img_path", jQuery("a.js_images_url").attr("href"));
			jQuery("#section-manager").processTemplate({ items: items });

			if (window.dctrl) {
				dctrl.backgroundOn();
			} else {
				jQuery("#popup-bg-auth").removeClass("dn");
			}

			this._de = jQuery("#section-manager");
			this.bind();
		});
	}

	/*
	* вешает обработчики на кнопку "закрыть"
	* инициализирует Sortable плагин от jQuery
	*/
	this.bind = function() {
		// кнопка закрыть
		jQuery(this._de).find(".js_neutral").bind("click", this, this.onClose);

		// таскалка
		jQuery(this._de).find("ul.js_menu").sortable({ update: this.onChangeOrder, _this: this });

		// выделение блока с разделом
		jQuery(this._de).find("li.js_item").bind("mouseover", this, this.onSelect);

		// кнопка создать
		jQuery(this._de).find("div.js_add a").bind("click", this, this.onCreate);

		jQuery(this._de).find("li.js_item a.js_item_edit").bind("mousedown", this, this.onItemEdit);

		jQuery(this._de).find("li.js_item a.js_item_del").bind("mousedown", this, this.onItemDelete);

	}

	/*
	* Обработчик удаления события. Выводит диалог, если согласны, то посылает запрос,
	* смотрит статус, удаляет элемент из ДОМ.
	*
	*/
	this.onItemDelete = function(event) {
		event.preventDefault();
		var _this = event.data;
		var elt = jQuery(this).parents("li.js_item");
		var oid = _this._getOidByElement(elt);
		if (confirm('Вы уверены, что хотите удалить этот раздел?')) {
			cp.set_env_object(_this);
			cp.call(_this._ajax_url, 'ajax_rmSection', function(result) {
				if (result.ajaxResponse[0].data==0) {
					this._rmItem(oid);
				} else {
					alert("Ошибка обработки запроса на сервере.");
				}
			}, oid);
		} else {
			// не уверен, не наливай ;)
		}
		return false;
	}

	this.onItemEdit = function(event) {
		event.preventDefault();
		var _this = event.data;
		var elt = jQuery(this).parents("li.js_item");
		var ss = new SectionSettings(_this, _this._getOidByElement(elt));
		jQuery(_this._de).hide();
	}

	/*
	* Обработчик добавления раздела.
	* Создает объект новой формы и передает ему управление.
	*/
	this.onCreate = function(event) {
		event.preventDefault();
		var _this = event.data;
		var sc = new SectionCreator(_this);
		jQuery(_this._de).hide();
	}

	/*
	* Происходит вызов этой функции при передаче управления из других состояний.
	* На момент написания мною было три состояния:
	*  - управление разделами (класс SectionsManager),
	*  - создание раздела (SectionCreator),
	*  - редактирование раздела (SectionSettings)
	*/
	this.onBack = function() {
		jQuery(this._de).remove();
		this.initDom();
	}

	/*
	* Удалить из DOM контрол раздела с oid
	*/
	this._rmItem = function(oid) {
		jQuery(this._getElementByOid(oid)).remove();
	}

	/*
	* Получить ид раздела по его dom элементу
	*/
	this._getOidByElement = function(elt) {
		return jQuery(elt).attr("id").substr(4) * 1;
	}

	/*
	* Получить dom элемент по его ид раздела
	*/
	this._getElementByOid = function(oid) {
		return jQuery("#sect"+oid);
	}

	this.onSelect = function(event) {
		event.preventDefault();
		var _this = event.data;

		jQuery(_this._getElementByOid(_this.selected_oid)).removeClass("active-");
		_this.selected_oid = _this._getOidByElement(this);
		jQuery(_this._getElementByOid(_this.selected_oid)).addClass("active-");
	}

	this.onClose = function(event) {
		event.preventDefault();

		var _this = event.data;
		jQuery(_this._de).remove();

		if (window.dctrl) {
			dctrl.backgroundOff();
		} else {
			jQuery("#popup-bg-auth").addClass("dn");
		}

		cp.set_env_object(_this);
		cp.call(_this._ajax_url, 'ajax_getSections', function(result) {
			var items = new Array();
			if (result.ajaxResponse[0].section) {
				jQuery(result.ajaxResponse[0].section).each(
				function() {
					var item = new Array();
					item['oid'] = this.oid[0].data;
					item['num'] = this.num[0].data;
					item['title'] = this.title[0].data;
					item['items_count'] = this.items_cnt[0].data;
					item['color'] = this.color[0].data;
					item['url'] = this.url[0].data;
					item['show_in_main_menu'] = this.show_in_main_menu[0].data;
					items.push(item);
				}
				);
			}

			var root = result.ajaxResponse[0].community_url[0].data + '/';

			var $menu, tpl;
			if ( jQuery(".js-tdi-menu").length ) {
			    $menu = jQuery(".js-tdi-menu");
			    $menu.empty("");
			    tpl = function(s) { return ''+
				'<li><a class="s'+s.color+'" href="'+s.href+'">'+s.title+'</a></li>'};

			} else if ( jQuery("#tdiMenuGautama").length ) {
			    var $menu = jQuery('<ul id="tdiMenuUL" class="list-">');
			    jQuery("#tdiMenuGautama").empty("").append($menu);

			    $menu.append('<li><a href="' + root + 'showfeed">Все записи</a></li>');
			    tpl = function(s) { return ''+
				'<li><a href="'+s.href+'">'+s.title+'</a></li>'};
			}

			if ($menu) {
			    for ( var i=0; i<items.length; i++ ) {
				if ( items[i]['show_in_main_menu'] > 0 ) {
				    var color = items[i]['color'];
				    if ( 1 == color.length ) {
					color = '0' + color;
				    }
				    $menu.append(tpl({
						'color': color, 
						'href' : root + items[i]['url'], 
						'title': items[i]['title']
				    }));
				}
			    }
			}
		});
	}

	this.onChangeOrder = function(e, ui) {
		// сохранить последовательность элементов на сервере
		var oids = new Array();
		var _this = ui.options._this;
		jQuery(this).find("li.js_item:not(.ui-sortable-helper)").each(
		function() {
			var id = _this._getOidByElement(this);
			if (oids.length==0) {
				oids[0] = id;
			} else {
				oids[oids.length] = id;
			}
		}
		);

		cp.set_env_object(_this);
		cp.call(_this._ajax_url, 'ajax_upSectionsOrder', function(result) {
			if (result.ajaxResponse[0].data != 0) { alert("Ошибка на стороне сервера. Порядок разделов не сохранен."); }
		}, oids);
	}
}

/**
* Контроллер формы. Умеет рендерить форму, послать данные на сервер, обработать ответ.
* Отрендерить с учетом данных, не прошедших валидацию. Передает управление родительскому объекту,
* методам onSubmit, onFormSuccess и onClose. Инициализируется элементом внутрь которого будет произведен рендеринг.
*
* Те форма сама по себе не делает сабмит, она предпочитает передать это дело родителю.
*
* @author Alexander Sibiryakov
*/
function SectionForm(fe, parent) {
	this.form_elt = fe;
	this.template = null;
	this.parent = parent; // родительский объект, передать ему управление при "выходе" из формы

	this._tpl_url = jQuery("a.js_tpl_url").attr("href");
	this._ajax_url = jQuery("a.js_sect_settings_url").attr("href");
	this._tabs_ui = null;

	// возможно эти данные нужно подгружать динамически с сервера
	this.doctypes = { doc : 'Текст', image : 'Изображения', link : 'Ссылки', file: 'Файлы', issue: 'Выпуски', review: 'Рецензии', vote: 'Голосования' };
	this.feeds = { showfeed: 'Лента', showforum: 'Форум', showalphabet: 'Алфавитный список', showfiles: 'Файлы', showgallery: 'Галерея', showissues: 'Список выпусков' };

	// используется для создания структуры для рендеринга групп чек боксов (вкладка "Права")
	this.roles = [ {oid: 9, name: 'Модератор'}, { oid: 12, name: 'Участник сообщества'} , { oid: 15, name: 'Зарегистрированный пользователь'}, { oid: 18, name: 'Аноним'} ];
	this.actions = [ {alias: 'item_create', name: 'Создание записей'}, {alias: 'item_read', name: 'Чтение записей'} , {alias: 'comment_create', name: 'Создание комментариев'}];

	/*
	* Отрендерит форму, и повесит контроллер табов
	*/
	this._renderForm = function(data) {
		if (this._tabs_ui) jQuery("#tab_container").find("ul.js_tabs").tabs("destroy");

		data['doctypes'] = this.doctypes;
		data['feeds'] = this.feeds;
		data['acl'] = this._makeAclStructure(data);

		jQuery(this.form_elt).setTemplate(this.template);
		jQuery(this.form_elt).setParam("img_path", jQuery("a.js_images_url").attr("href"));
		jQuery(this.form_elt).processTemplate(data);

		this._tabs_ui = jQuery("#tab_container").find("ul.js_tabs").tabs({ show : function(ui) {
			jQuery(ui.tab).parents("ul").find("li").removeClass("current-");
			jQuery(ui.tab).parents("li").addClass("current-");
		}
		});

	}

	/*
	* Подготовит структуру данных для рендеринга групп с чекбоксами (для управления правами).
	* Если пришли данные формы (data['is_data'] == true)  то использует их для установки значений чекбоксов
	*/
	this._makeAclStructure = function(data) {
		var acl = [];
		var _this = this;
		jQuery(_this.roles).each(function() {
			var role = this;
			acl[acl.length] = { role_name: role.name };

			var role_acls = [];
			jQuery(_this.actions).each(function() {
				var role_acl = {};
				role_acl['oid'] = role.oid;
				role_acl['alias'] = this.alias;
				role_acl['name'] = this.name;
				role_acl['selected'] = 1;

				var acl_name = "acl["+role_acl['oid']+"]["+role_acl['alias']+"]";
				role_acl['dom_id'] = acl_name; // идентификатор id в dom браузера

				if (data['is_data']) { // пришли данные, тогда проставим флажок "выбрано" для чекбокса
					if (data['data'][acl_name] == 'on') { role_acl['selected'] = 1; } else { role_acl['selected'] = 0; }
				} else { // данных нет, тогда снимем/поставим флажок согласно значениям по умолчанию

					// анониму нельзя писать записи и комментарии
					if (role_acl['oid']==18 && (role_acl['alias']=='item_create' || role_acl['alias']=='comment_create')) role_acl['selected']=0;
				}
				role_acls[ role_acls.length ] = role_acl;
			});
			acl[acl.length-1]['role_acl'] = role_acls;
		});
		return acl;
	}

	this.render = function(data) {
		// рендерит и делает вставку в DOM

		// тут надо загрузить из сети шаблон, затем, пропарсить его
		if (this.template == null)
		this.template = jQuery.createTemplateURL(this._tpl_url +"/WG_SectionsManage:form");

		if (!data) var data={};

		data['is_errors'] = false;
		this._renderForm(data);
		this._bind();
	}

	/*
	* Вешает обработчики событий на кнопки "Сохранить" и "Закрыть"
	*/
	this._bind = function() {
		jQuery(this.form_elt).find(".js_buttons .js_accept").bind("click", this, this.onSubmit);
		jQuery(this.form_elt).find(".js_buttons .js_neutral").bind("click", this, this.onClose);
	}

	/*
	* Рендерит форму с ошибками обработки и с данными которые пользователь пытался засабмитить
	*/
	this.renderErrors = function(result) {
		jQuery(this.form_elt).setTemplate(this.template);
		jQuery(this.form_elt).setParam("img_path", jQuery("a.js_images_url").attr("href"));

		var data = {};
		data['is_errors'] = true;
		var errors = {};
		jQuery(result.ajaxResponse[0].error).each(
		function() {
			errors[ this.fieldname[0].data ] = this.errortext[0].data;
		}
		);
		data['errors'] = errors;
		data['is_data'] = true;
		data['data'] = this.getFormDataObject();

		this._renderForm(data);
		this._bind();
	}

	/*
	* Получить данные формы в виде объекта
	*/
	this.getFormDataObject = function() {
		var data = {};
		var dataArray = jQuery(this.form_elt).serializeArray();
		jQuery(dataArray).each(function() {
			data[this.name] = this.value;
		});
		return data;
	}

	/*
	* Получить сериализованные в строку с разделителями & данные формы
	* Используется для прямой отправки в урл
	*
	*/
	this.getFormData = function() {
		return jQuery(this.form_elt).serialize();
	}

	/*
	* Обработчик события "Сохранить". Если форма успешно засабмитилась то передаст управление родителю.
	* Если ошибки валидации - вызовет повторный рендеринг.
	*/
	this.onSubmit = function(event) {
		// отсылает на сервер данные и проводит там их валидацию
		// если вернулись ошибки, то их подсвечивает
		// если нет ошибок, то закрывает окно и передает управление SectionManager'у
		event.preventDefault();
		var _this = event.data;
		var data = _this.getFormData();
		_this.parent.onSubmit(data, _this.onSubmit_cb, _this);
	}

	/*
	* Этот метод выполнится после сабмита формы
	*/
	this.onSubmit_cb = function(result) {
		var status = result.ajaxResponse[0].data;
		if (status == 0) {
			this.parent.onFormSuccess();
			return;
		} else {
			// произошли ошибки
			if (status == 3) {
				// с валидацией
				this.renderErrors(result);
			} else {alert("Ошибка обработки запроса на сервере.");}
		}
	}

	/*
	* Обработчик события "закрыть форму" передает управление родительскому объекту.
	*/
	this.onClose = function(event) {
		event.preventDefault();
		var _this = event.data;
		_this.parent.onClose();
	}
}

/**
* Класс создания раздела. Рендерит пустую форму, делает сабмит, если ошибки валидации то рендерит повторно
* с использованием введенных данных.
*/
function SectionCreator(parent) {
	this._tpl_url = jQuery("a.js_tpl_url").attr("href");
	this._ajax_url = jQuery("a.js_sect_settings_url").attr("href");
	this.template = null;
	this.parent = parent;

	this.initDom = function() {
		jQuery(this.parent._de).after('<div id="section-creator"></div>');
		this._de = jQuery("#section-creator");
		this.template = jQuery.createTemplateURL(this._tpl_url +"/WG_SectionsManage:container");

		jQuery(this._de).setTemplate(this.template);
		jQuery(this._de).setParam("img_path", jQuery("a.js_images_url").attr("href"));
		jQuery(this._de).processTemplate({title: 'Создание раздела'});
		var form = jQuery(this._de).find("form.js_form");
		this.form = new SectionForm(form ,this);
		this.form.render();
	}

	this.onSubmit = function(data, callback, scope) {
		cp.set_env_object(scope);
		cp.call(this._ajax_url, "ajax_handleFormCreate", callback, data);
	}

	this.onFormSuccess = function() {
		this.onClose();
	}

	this.onClose = function() {
		this.form = null;
		jQuery(this._de).remove();
		this.parent.onBack();
	}

	this.initDom();
}

/**
* Класс редактирования раздела. По сути подгружает данные о разделе, затем создает форму и
* рендерит ее с использованием этих данных.
*/
function SectionSettings(parent, oid) {
	this.parent = parent;
	this._sets = null;
	this.oid = oid;
	this._ajax_url = jQuery("a.js_sect_settings_url").attr("href");
	this._tpl_url = jQuery("a.js_tpl_url").attr("href");
	this._de = null;
	this._form = null;
	this._template = null;

	this.retrSectSettings = function() {
		// получить данные настроек и положить их this._sets
		cp.set_env_object(this);
		cp.call(this._ajax_url, 'ajax_getSectionDetails',function(result) {
			this._sets = this._mapVars(result);
			this.initDom();
		}, this.oid);
	}

	/*
	* Делает маппинг переменных пришедших с сервера, в структуру пргодную для парсинга шаблонизатором
	*/
	this._mapVars = function(result) {
		var in_sect = result.ajaxResponse[0].section[0];
		var out_sect = {};

		var actions = ["item_create", "item_read", "comment_create"];

		out_sect['title'] = in_sect['title'][0].data;
		out_sect['url'] = in_sect['url'][0].data;
		out_sect['feed'] = in_sect['feed'][0].data;
		out_sect['def_doctype'] = in_sect['def_doctype'][0].data;
		out_sect['tags'] = in_sect['tags'][0].data;
		out_sect['show_in_main_menu'] = in_sect['show_in_main_menu'][0].data==1 ? true : false;

		jQuery(in_sect['acl'][0].role_acl).each(function() {
			var name_part = "acl["+this.data+"]";
			var role_acl = this;
			jQuery(actions).each(function() {
				var name = name_part+"["+this+"]";
				if (role_acl[this][0].is_allowed[0].data == 1) out_sect[name] = "on";
			});

		});
		console.log(out_sect);
		return out_sect;
	}

	this.initDom = function() {
		// отрендерить и повесить обработчики
		jQuery(this.parent._de).after('<div id="section-settings"></div>');
		this._de = jQuery("#section-settings");
		this._template = jQuery.createTemplateURL(this._tpl_url +"/WG_SectionsManage:container");

		jQuery(this._de).setTemplate(this._template);
		jQuery(this._de).setParam("img_path", jQuery("a.js_images_url").attr("href"));
		jQuery(this._de).processTemplate({title: 'Редактирование раздела'});
		var form = jQuery(this._de).find("form.js_form");
		this._form = new SectionForm(form, this);
		this._form.render({ data: this._sets, is_data: true });

	}

	this.onSubmit = function(data, callback, scope) {
		cp.set_env_object(scope);
		cp.call(this._ajax_url, "ajax_handleFormEdit", callback, this.oid,  data);
	}

	this.onFormSuccess = function() {
		this.onClose();
	}

	this.onClose = function() {
		// закрыть и убить себя
		this._form = null;
		jQuery(this._de).remove();
		this.parent.onBack();
	}

	this.retrSectSettings();
}
